import Arbol23
import HUnit
import Char

-- evaluar t para correr todos los tests
t = runTestTT allTests

allTests = test [ 
    "ejercicio 1" ~: testsEjercicio1,
    "ejercicio 2" ~: testsEjercicio2,
    "ejercicio 3" ~: testsEjercicio3,
    "ejercicio 4" ~: testsEjercicio4,
    "ejercicio 5" ~: testsEjercicio5
    ]

------- Data de prueba -------

--Ejemplo de uso de foldA23.
--Cuenta la cantidad de nodos de cualquier tipo.
nodos :: Arbol23 a b -> Int
nodos = foldA23 (const 1) (\b nodosL nodosR -> 1 + nodosL + nodosR) (\b1 b2 nodosL nodosM nodosR -> 1 + nodosL + nodosM + nodosR)

--Ejemplo de uso de mapA23.
--Incrementa en 1 el valor de las hojas.
incrementarHojas::Num a =>Arbol23 a b->Arbol23 a b
incrementarHojas = mapA23 (+1) id

arbolito1::Arbol23 Char Int
arbolito1 = Tres 0 1
                (Dos 2 
                    (Hoja 'a')
                    (Hoja 'b'))
                (Tres 3 4 
                    (Hoja 'c') 
                    (Hoja 'd') 
                    (Dos 5 
                        (Hoja 'e')
                        (Hoja 'f')))
                (Dos 6 
                    (Hoja 'g') 
                    (Dos 7 
                        (Hoja 'h') 
                        (Hoja 'i')))

arbolito2::Arbol23 Int Bool
arbolito2 = Dos True 
                (Hoja (-1)) 
                (Tres False True 
                    (Hoja 0) 
                    (Hoja (-2)) 
                    (Hoja 4))

mapEnArbolito2::Arbol23 Int Bool
mapEnArbolito2 = Dos False 
                (Hoja 0) 
                (Tres True False 
                    (Hoja 1) 
                    (Hoja (-1)) 
                    (Hoja 5))

arbolito3::Arbol23 Int (Int->Int->Int)
arbolito3 = Dos (+) 
                (Tres (*) (-) 
                    (Hoja 1) 
                    (Hoja 2) 
                    (Hoja 3)) 
                (incrementarHojas arbolito3)

a0 :: Arbol23 Int Char
a0 = Hoja 0

a1:: Arbol23 Int Char
a1 = Dos 'a' (Hoja 0) (Hoja 1)

a2:: Arbol23 Int Char
a2 = Tres 'a' 'b' (Hoja 0) (Hoja 1) (Hoja 2)

a3 :: Arbol23 Int Char
a3 = Tres 'a' 'b' (Dos 'c' (Hoja 0) (Hoja 1)) (Hoja 2) (Dos 'd' (Hoja 3) (Hoja 4))

ejemplo1Consigna :: Arbol23 Int Char
ejemplo1Consigna = Dos 'p' 
                    (Dos 'l' 
                        (Dos 'g'
                            (Hoja 5)
                            (Hoja 2))
                        (Tres 'r' 'a' 
                            (Hoja 0)
                            (Hoja 1)
                            (Hoja 12)))

                    (Dos 'p' 
                        (Tres 'n' 'd'
                            (Hoja (-3))
                            (Hoja 4)
                            (Hoja 9))
                        (Dos 'e'
                            (Hoja 20)
                            (Hoja 7)))

ejemplo1ConsignaMap :: Arbol23 Int Char
ejemplo1ConsignaMap = Dos 'P' 
                        (Dos 'L' 
                            (Dos 'G'
                                (Hoja 9)
                                (Hoja 6))
                            (Tres 'R' 'A' 
                                (Hoja 4)
                                (Hoja 5)
                                (Hoja 16)))

                        (Dos 'P' 
                            (Tres 'N' 'D'
                                (Hoja 1)
                                (Hoja 8)
                                (Hoja 13))
                            (Dos 'E'
                                (Hoja 24)
                                (Hoja 11)))

ejemplo1ConsignaTruncar :: Arbol23 Int Char
ejemplo1ConsignaTruncar = Dos 'p' 
                            (Dos 'l' 
                                (Dos 'g'
                                    (Hoja 0)
                                    (Hoja 0))
                                (Tres 'r' 'a' 
                                    (Hoja 0)
                                    (Hoja 0)
                                    (Hoja 0)))

                            (Dos 'p' 
                                (Tres 'n' 'd'
                                    (Hoja 0)
                                    (Hoja 0)
                                    (Hoja 0))
                                (Dos 'e'
                                    (Hoja 0)
                                    (Hoja 0)))

------- Tests por ejercicio -------

testsEjercicio1 = test [
    1 ~=? nodos a0,
    3 ~=? nodos a1,
    4 ~=? nodos a2,
    8 ~=? nodos a3
    ]

testsEjercicio2 = test [
    [0]                     ~=? hojas a0,
    [0,1]                   ~=? hojas a1,
    [0,1,2]                 ~=? hojas a2,
    [0,1,2,3,4]             ~=? hojas a3,
    "abcdefghi"             ~=? hojas arbolito1,
    [1,2,3,2,3,4,3,4,5,4]   ~=? take 10 (hojas arbolito3),


    []                  ~=? internos a0,
    "a"                 ~=? internos a1,
    "ab"                ~=? internos a2,
    "abcd"              ~=? internos a3,
    [0,1,2,3,4,5,6,7]   ~=? internos arbolito1,
    [True,False,True]   ~=? internos arbolito2,

    True    ~=? esHoja a0,
    False   ~=? esHoja a1,
    False   ~=? esHoja a2
    ]

testsEjercicio3 = test [
    ejemplo1ConsignaMap ~=? mapA23 (+4) toUpper ejemplo1Consigna,
    [0,1,-1,5]          ~=? hojas (incrementarHojas arbolito2),
	mapEnArbolito2		~=?	mapA23 (+1) not arbolito2,
	arbolito2			~=? mapA23 id id arbolito2,
	a0					~=? mapA23 id id a0,
	Hoja 1				~=? mapA23 (+1) id a0
    ]

testsEjercicio4 = test [
    ejemplo1ConsignaTruncar             		~=? truncar 0 3 ejemplo1Consigna,
    [1,2,3,2,3,4,3,4,5,4,5,6,0,0,0,0,0] 		~=? hojas (truncar 0 6 arbolito3),
	a0 											~=? truncar 0 0 a0,
	Hoja 'a'							 		~=? truncar 'a' 0 arbolito1,
	Tres 0 1 (Hoja 'a')	(Hoja 'a') (Hoja 'a')	~=? truncar 'a' 1 arbolito1
    ]

testsEjercicio5 = test [
    -1  ~=? evaluar (truncar 0 3 arbolito3),
    1   ~=? evaluar (truncar 0 4 arbolito3),
    8   ~=? evaluar (truncar 0 5 arbolito3),
    22  ~=? evaluar (truncar 0 6 arbolito3),
 	0	~=? evaluar (truncar 0 2 arbolito3),
 	0	~=? evaluar (truncar 0 1 arbolito3),
 	2	~=? evaluar (truncar 1 1 arbolito3),
 	1	~=? evaluar (truncar 1 0 arbolito3)
    ]
